# Django Template and HTML Generation.
# --
# To know my deed: tis better to not know myself.
# Liver of blaspheming Jew.
# Thine linen bedsheets of countenance do fear!
# Your royal preparation makes us hear something.
#
from pdb import runcall
Absent = object()

def traceOff(function):
    # Do not trace!
    function.__trace_off__ = True
    return function

# Base Generator Routines & Types.
from types import GeneratorType as generator
def toTemplateString(result):
    if type(result) in (list, tuple, generator):
        # Recursive flattening and concatenation.
        return ''.join(toTemplateString(el) for el in result)

    return str(result)

class Model:
    def __init__(self, type, *args, **kwd):
        self.type = type
        self.args = args
        self.kwd = kwd

    @staticmethod
    def MergeDictionary(d1, d2):
        d3 = d1.copy()
        d3.update(d2)
        return d3

    def __call__(self, *args, **kwd):
        args = self.args + args
        kwd = self.MergeDictionary(self.kwd, kwd)
        return toTemplateString(self.type(*args, **kwd))

    __str__ = __call__

    def Model(self, *args, **kwd):
        return self.__class__(self, *args, **kwd)

def toQuotedString(s):
    return '"%s"' % repr('"' + s)[2:-1]

def Element(element):
    # Decorator.
    def wrapping(*args, **kwd):
        return toTemplateString(element(*args, **kwd))
    def thisModel(*args, **kwd):
        return Model(element, *args, **kwd)

    wrapping.Model = thisModel
    return wrapping

def Parameters(*args):
    return args

@Element
def Tag(name, *parameters):
    params = ' '.join(map(str, parameters))
    yield '{%% %s%s%s %%}' % (name, params and ' ' or '', params)

@Element
def ClosedTag(name, parameters, *content, **kwd):
    yield Tag(name, *parameters)
    yield content

    closing = kwd.pop('closing')
    if closing is True:
        yield Tag('end' + name)
    elif callable(closing):
        yield Tag(str(closing(name)))
    elif isinstance(closing, basestring):
        yield Tag(closing)

@Element
def Child(parent, *content):
    yield Tag('extends', *Parameters(toQuotedString(parent)))
    yield content

@Element
def Block(name, *content):
    yield ClosedTag('block', Parameters(name), *content,
                    **dict(closing = 'endblock ' + name))

@Element
def Variable(name, *filters):
    yield '{{ ' + name
    for f in filters:
        yield '|'
        yield f

    yield ' }}'

class VariableGenerator(object):
    def __init__(self, value, *filters):
        self._value = value
        self._filters = filters

    def __getattr__(self, name):
        if name.startswith('_'):
            return object.__getattr__(self, name)

        value = self._value
        return self.__class__('%s%s%s' % (value and value or '', value and '.' or '', name),
                              *self._filters)

    def __add__(self, f):
        self._filters += f
        return self

    def __str__(self):
        return Variable(self._value, *self._filters)

Variable.Name = VariableGenerator('')
del VariableGenerator

@Element
def Filter(name, parameter = Absent):
    if parameter is Absent:
        return str(name)

    return '%s:%s' % (name, toQuotedString(parameter))

class HTMLElement:
    def __init__(self, name, *args, **kwd):
        self.name = name
        self.self_closing = kwd.pop('self_closing', False) or False
        self.Model = Model(self, *args, **kwd)

    @classmethod
    def TranslateAttributes(self, attributes):
        for (name, value) in attributes.iteritems():
            yield (self.TRANSLATIONS.get(name, name), value)

    TRANSLATIONS = dict(className = 'class')

    @Element
    def __call__(self, *content, **attributes):
        attributes = ' '.join('%s="%s"' % (name, value) for (name, value) in self.TranslateAttributes(attributes))
        if self.self_closing:
            assert not content
            yield '<%s%s%s />' % (self.name, attributes and ' ' or '', attributes)
        else:
            yield '<%s%s%s>' % (self.name, attributes and ' ' or '', attributes)
            yield content
            yield '</%s>' % self.name

_registered_doctypes = {'': 'HTML'}
def DOCTYPE(name = ''):
    return '<!DOCTYPE %s>' % _registered_doctypes.get(name, name)

import template_repository
template_repository.install()

from lib import *
from rendering import *

from template_repository import RegisterTemplate
